package handlers;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import database.Connect;

/**
 * Handles the Weather Stations
 * 
 * @author Nils Berlijn & Henderikus Harms
 */	
public class WeatherStationHandler implements Runnable
{
	private Boolean running;
	private Socket socket;
	private String input;
	private BufferedReader reader;
	private HashMap<String, String> map;

	/**
	 * Initialize the WeatherStationHandler
	 * 
	 * @param socket
	 * @throws IOException 
	 */
	public WeatherStationHandler(Socket socket) throws IOException
	{
		this.running = true;
		this.socket = socket;
		this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
	}
	
	/**
	 * Reading the incoming XML data
	 * Parse it
	 */
	@Override
	public void run() 
	{
		try 
		{
			while((input = reader.readLine()) != null)
			{	
				parse(input);
			}
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * Parses the incoming data and give it back in a HashMap
	 * After the incoming data ends it goes to the verify method
	 * 
	 * @param input Data to be parsed
	 * @param map HashMap with all the parsed data
	 */
	private void parse(String input)
	{
		if(input.endsWith("<MEASUREMENT>"))
		{
			map = new HashMap<String, String>();
		}
		else if(input.endsWith("</MEASUREMENT>"))
		{
			verify(map);
		}
		else
		{
			// REGEX as parser
			Pattern regex = Pattern.compile("<(\\w+)>(.*?)<(/\\w+)>");
			Matcher matcher = regex.matcher(input);

			// Looking for a match
		    if(matcher.find()) 
		    {
		    	// Add the key and value to the HashMap
		    	map.put(matcher.group(1), matcher.group(2));
		    }  	
		}		
	}
	
	/**
	 * Check if the data is valid
	 * If so it will insert the data to the Database
	 * 
	 * @param map The HashMap with the incoming data
	 */
	private void verify(HashMap<String, String> map)
	{
		boolean valid = true;	
		if(map.size() == 14)
		{
			if(map.get("STN") == null){
				valid = false;
			}
			if(map.get("DATE") == null){
				valid = false;
			}
			if(map.get("TIME") == null){
				valid = false;
			}
			if(map.get("TEMP") == null){
				valid = false;
			}
			if(map.get("DEWP") == null){
				valid = false;
			}
			if(map.get("STP") == null){
				valid = false;
			}
			if(map.get("SLP") == null){
				valid = false;
			}
			if(map.get("VISIB") == null){
				valid = false;
			}
			if(map.get("WDSP") == null){
				valid = false;
			}
			if(map.get("PRCP") == null){
				valid = false;
			}
			if(map.get("SNDP") == null){
				valid = false;
			}
			if(map.get("FRSHTT") == null){
				valid = false;
			}
			if(map.get("CLDC") == null){
				valid = false;
			}
			if(map.get("WNDDIR") == null){
				valid = false;
			}
			if (valid){
				saveData(map);
				System.out.println("Data is valid");
			}else{
				System.out.println("Data is not valid");
			}	
		}
		else
		{
			System.out.println("Data is not valid");			
		}
		
		// TODO Expand the verify method
	}
	
	/**
	 * Inserts a HashMap into the Database
	 * The Connect class will be used to get a connection with the Database
	 * 
	 * @param map The data that will be put into the Database
	 */
    private void saveData(HashMap<String, String> map)
    {
        Connect.open();
        
        PreparedStatement statement = null;
        
        String insertSQL = 	"INSERT INTO measurement" + 
        					"(stn, date, time, temp, dewp, stp, slp, visib, wdsp, prcp, sndp, frshtt, cldc, wnddir) VALUES" +
        					"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; 
        
        try 
        {
            statement = Connect.connection.prepareStatement(insertSQL);

            statement.setInt(1, Integer.parseInt(map.get("STN")));
            statement.setString(2, map.get("DATE"));
            statement.setString(3, map.get("TIME"));
            statement.setDouble(4, Double.parseDouble(map.get("TEMP")));
            statement.setDouble(5, Double.parseDouble(map.get("DEWP")));
            statement.setDouble(6, Double.parseDouble(map.get("STP")));
            statement.setDouble(7, Double.parseDouble(map.get("SLP")));
            statement.setDouble(8, Double.parseDouble(map.get("VISIB")));
            statement.setDouble(9, Double.parseDouble(map.get("WDSP")));
            statement.setDouble(10, Double.parseDouble(map.get("PRCP")));
            statement.setDouble(11, Double.parseDouble(map.get("SNDP")));
            statement.setString(12, map.get("FRSHTT"));
            statement.setDouble(13, Double.parseDouble(map.get("CLDC")));
            statement.setInt(14, Integer.parseInt(map.get("WNDDIR")));

            statement.executeUpdate();
            
            System.out.println("Inserting data to the Database");

            Connect.close();
        } 
        catch (SQLException e) 
        {
        	e.printStackTrace();
        }
    }		
}
